(ns redrouter.utils
  (:require
   [reagent.core :as r]
   [clojure.string :as s]
   [clojure.walk :refer [postwalk]]
   [camel-snake-kebab.core :as csk]
   [clojure.set :refer [rename-keys]]
   [goog.object :refer [getValueByKeys]]))

(defn map-keys->camel-case
  "Stringifys all the keys of a cljs hashmap and converts them
   from kebab case to camel case. If :html-props option is specified,
   then rename the html properties values to their dom equivalent
   before conversion"
  [data & {:keys [html-props]}]
  (let [convert-to-camel (fn [[key value]]
                           [(csk/->camelCase (name key)) value])]
    (postwalk (fn [x]
                  (if (map? x)
                    (let [new-map (if html-props
                                    (rename-keys x {:class :className :for :htmlFor})
                                    x)]
                      (into {} (map convert-to-camel new-map)))
                    x))
                data)))

(defn call-js-func
  "Calls a javascript function, converting the keys for any arguments
   that are hashmaps from kebab case to camel case
   * func - the native javascript to be called"
  [func & args]
  (js->clj
   (apply func (clj->js (map #(-> % (map-keys->camel-case)) args)))
   :keywordize-keys true))

(defn call-func
  "Calls the function"
  [ns fun-name & args]
  (let [fun (apply getValueByKeys ns fun-name)]
    (apply call-js-func fun args)))

(defn ->reagent-component
  "react组件转为reagent组件"
  [ns module-path]
  (r/adapt-react-class (apply getValueByKeys ns module-path)))

(defn get-route-paths
  "获取路由path"
  [route]
  (mapv
   :path
   (filter
    #(not (boolean (seq (:routes %))))
    (tree-seq
     #(boolean (seq (:routes %)))
     :routes
     route))))

(defn get-route-compoents [route]
  (let [wrappers (or (:wrappers route) [])]
    (conj wrappers (:component route))))

(defn wrapper-compoents
  ([compoents route-props last-compoent]
   (reduce
    (fn [v1 v2]
      [:f> v2 route-props v1])
    last-compoent
    (reverse compoents)))
  ([compoents route-props]
   (wrapper-compoents compoents route-props [:<>])))
